<?php

namespace Biz\tools;

use Biz\cache\wiki\TbkUrl;
use Doraemon\pockets\config\IniConfig;
use Doraemon\tools\IdParse;
use Doraemon\tools\Log;
use TbkActivityInfoGetRequest;
use TbkCouponConvertRequest;
use TbkDgMaterialOptionalRequest;
use TbkItemInfoGetRequest;
use TbkOrderDetailsGetRequest;
use TbkScPublisherInfoSaveRequest;
use TbkSpreadGetRequest;
use TbkSpreadRequest;
use TbkTpwdCreateRequest;
use TbTopClient;
use TopAuthTokenCreateRequest;

class TbkUnion
{
    const PID = 'mm_394050001_454500301_108710850472';//app
    const SITE_ID = '454500301';
    const ADZONE_ID = 108710850472;


    const PID2 = 'mm_394050001_454500301_109049300371';//微信公众号
    const ADZONE_ID2 = 109049300371;

    const PID3 = 'mm_394050001_454500301_110094050149';//微信群
    const ADZONE_ID3 = 110094050149;

    const PID4 = 'mm_394050001_454500301_111751050443';//设计师线下带货
    const ADZONE_ID4 = 111751050443;

    const ADZONE_TEXT_MAP = [
        self::ADZONE_ID => 'App',
        self::ADZONE_ID2 => '微信公众号',
        self::ADZONE_ID3 => '微信群',
        self::ADZONE_ID4 => '设计师线下带货'
    ];

    const ADZONE_ID_MAP = [
        self::ADZONE_ID,
        self::ADZONE_ID2,
        self::ADZONE_ID3,
        self::ADZONE_ID4
    ];

    const _CONFIG_FILE_ = 'tbk';

    //场景ID：1，2，3
    const BIZ_SCENE_ID1 = 1;//1-动态ID转链场景（支持新商品ID转换）——该场景权限为常规调用
    const BIZ_SCENE_ID2 = 2;//2-消费者比价场景（支持原始商品ID转新商品ID）——符合标准者可尝试调用
    const BIZ_SCENE_ID3 = 3;//3-商品库导购场景（支持库内B段新商品ID转换）（不填默认为1）——符合标准者可尝试调用  高效转链和商详简版接口支持

    const PLATFORM_PC = 1;
    const PLATFROM_MOBILE = 2;

    const INVITER_CODE_COMMON = 'TASZPF';//通用备案（common）
    const INVITER_CODE_OFFLINE_SHOP = '3U295H';//线下门店（offlineShop）
    const INVITER_CODE_OFFLINE_PERSON = 'R54MLN';//线下个人（offlinePerson）

    //通用备案邀请链接
    const INVITER_CODE_COMMON_URL = 'https://mos.m.taobao.com/inviter/register?inviterCode=TASZPF&src=pub&app=common';
    //线下门店
    const INVITER_CODE_OFFLINE_STORE_URL = 'https://mos.m.taobao.com/inviter/offline-verify?inviterCode=3U295H&src=pub&app=offlineShop&type=shop';
    //线下个人
    const INVITER_CODE_OFFLINE_USER_URL = 'https://mos.m.taobao.com/inviter/offline-verify?inviterCode=R54MLN&src=pub&app=offlinePerson';

    //授权场景-设计师带货生成渠道关系ID
    const OAUTH_SCENE_DESIGNER_COMMERCE_RID = 'designer_commerce_rid';//设计师带货生成渠道关系ID

    //授权场景
    const OAUTH_SCENE_MAP = [
        self::OAUTH_SCENE_DESIGNER_COMMERCE_RID
    ];

    const OAUTH_SCENE_DESIGNER_COMMERCE_EXPIRE_TIME = 10 * 60;

    private static $topClient = null;

    private static $callBackUrl = 'https://tapi.haohaozhu.cn/taobao/union';

    private static $oAuthUrl = 'https://oauth.taobao.com/authorize?response_type=code&client_id=%s&redirect_uri=%s&state=%s&view=web';

    const OAUTH_DESIGNER_COMMERCE_REDIRECT_URL = 'https://peanut.haohaozhu.cn/user/auth-status';

    /**
     * @param int|string $itemId
     * @param int $adZoneId
     * @param string $relationId
     * @param int $bizSceneId 场景ID
     * @return array
     * taobao.tbk.coupon.convert(淘宝客-推广者-单品券高效转链)
     */
    public static function tbkCouponConvert(
        $itemId,
        $adZoneId = self::ADZONE_ID,
        $relationId = '',
        int $bizSceneId = self::BIZ_SCENE_ID1
    ): array
    {

        if (!$itemId) {
            return [];
        }
        $req = new TbkCouponConvertRequest;
        $req->setAdzoneId($adZoneId);//推广位id，mm_xx_xx_xx pid三段式中的第三段
        $req->setItemId($itemId);//淘客商品id  测试参数：653233153243
        $req->setPlatform(self::PLATFROM_MOBILE);//1：PC，2：无线，默认：１
        $req->setRelationId($relationId);//渠道管理ID
        $req->setBizSceneId($bizSceneId);//场景ID，见常量备注
        $resp = self::topClient()->execute($req);
        $data = self::_getArrayData($resp);

        if (isset($data['result']['results'])) {
            Log::info('taobao.tbk.coupon.convert(淘宝客-推广者-单品券高效转链)', [$itemId, $adZoneId, $relationId]);
            return $data['result']['results'] ?? [];
        } else {
            Log::error('taobao.tbk.coupon.convert(淘宝客-推广者-单品券高效转链)', $resp);
            return [];
        }
    }

    /**
     * @param $req
     * @param $msgKey
     * @return array|mixed
     */
    private static function handleResultsResponse($req, $msgKey)
    {
        $resp = self::topClient()->execute($req);
        $data = self::_getArrayData($resp);
        if (isset($data['results'])) {
            return $data['results'] ?? [];
        } else {
            Log::error($msgKey, $resp);

            return [];
        }
    }

    /**
     * @param $req
     * @param $msgKey
     * @return array|mixed
     */
    private static function handleDataResponse($req, $msgKey)
    {
        $resp = self::topClient()->execute($req);
        $data = self::_getArrayData($resp);
        if (isset($data['data'])) {
            return $data['data'] ?? [];
        } else {
            Log::error($msgKey, $resp);

            return [];
        }
    }

    /**
     * @return \TbTopClient
     */
    private static function topClient(): TbTopClient
    {
        if (is_null(self::$topClient)) {
            $config = self::_getAppConfig();
            $topClient = new TbTopClient;
            $topClient->appkey = $config['default']['appkey'];
            $topClient->secretKey = $config['default']['secretKey'];
            $topClient->format = 'json'; //响应格式。默认为xml格式，可选值：xml，json。
            self::$topClient = $topClient;
        }

        return self::$topClient;
    }

    private static function _getAppConfig()
    {
        return IniConfig::getConfigFile(static::_CONFIG_FILE_);
    }

    private static function _getArrayData($resp)
    {
        $data = [];
        //tbTopClient 返回的异常处理会有对象
        if (is_array($resp) && !empty($resp)) {
            $data = $resp;
        }
        return $data;
    }

    /**
     * @param string $url
     * @return array|mixed
     * taobao.tbk.tpwd.create( 淘宝客-公用-淘口令生成 )
     */
    public static function tbkTpwdCreate(string $url)
    {
        if (!$url) {
            return [];
        }
        $req = new TbkTpwdCreateRequest;
        $req->setUrl($url); //示例：https://s.click.taobao.com/YI3Uopu	联盟官方渠道获取的淘客推广链接，请注意，不要随意篡改官方生成的链接，

        $resp = self::topClient()->execute($req);
        $data = self::_getArrayData($resp);
        if (isset($data['data'])) {
            return $data['data'] ?? [];
        } else {
            Log::error('taobao.tbk.tpwd.create( 淘宝客-公用-淘口令生成 )', $resp);

            return [];
        }
    }

    /**
     * @param string $itemId
     * @param int $platform
     * @param int $bizSceneId 场景ID（见常量备注）
     * @return array|mixed
     * taobao.tbk.item.info.get( 淘宝客-公用-淘宝客商品详情查询(简版))
     */
    public static function tbkItemInfo(string $itemId, int $platform = self::PLATFROM_MOBILE, int $bizSceneId = self::BIZ_SCENE_ID1)
    {
        if (!$itemId) {
            return [];
        }
        $req = new TbkItemInfoGetRequest;
        $req->setNumIids($itemId);//商品ID串，用,分割，最大40个
        $req->setPlatform($platform);//链接形式：1：PC，2：无线，默认：１
        $req->setBizSceneId($bizSceneId);//场景ID：1，2，3，见常量备注

        return self::handleResultsResponse($req, 'taobao.tbk.item.info.get( 淘宝客-公用-淘宝客商品详情查询(简版))');
    }

    /**
     * @param $q 商品筛选-查询词
     * @param $page
     * @param $pageSize
     * @param $adzoneId
     * @param int $bizSceneId 场景ID（见常量备注）该接口不支持场景ID3
     * @return array|mixed
     * taobao.tbk.dg.material.optional( 淘宝客-推广者-物料搜索 )
     */
    public static function tbkDgOpMaterialOptional($q, $page = 1, $pageSize = 20, $adzoneId = self::ADZONE_ID, int $bizSceneId = self::BIZ_SCENE_ID1)
    {
        //可获取到白底图、商品短名
        $req = new TbkDgMaterialOptionalRequest;
        $req->setAdzoneId($adzoneId);
        $req->setQ($q);
        $req->setPageNo($page);
        $req->setPageSize($pageSize);
        $req->setBizSceneId($bizSceneId);
        $resp = self::topClient()->execute($req);
        $data = self::_getArrayData($resp);
        $result = $data['result_list']['map_data'] ?? [];
        return $result;
    }

    /**
     * @param int $queryType 查询时间类型，1：按照订单淘客创建时间查询，2:按照订单淘客付款时间查询，3:按照订单淘客结算时间查询，4:按照订单更新时间；
     * @param string $startTime 订单查询开始时间
     * @param string $endTime 订单查询结束时间，订单开始时间至订单结束时间，中间时间段日常要求不超过3个小时，但如618、双11、年货节等大促期间预估时间段不可超过20分钟，超过会提示错误，调用时请务必注意时间段的选择，以保证亲能正常调用！
     * @param int $pageSize 页大小，默认20，1~100
     * @param int $orderScene 场景订单场景类型，1:常规订单，2:渠道订单，3:会员运营订单，默认为1
     * @param string $positionIndex 位点，除第一页之外，都需要传递；前端原样返回
     * @return array|mixed
     * taobao.tbk.order.details.get( 淘宝客-推广者-所有订单查询 )
     */
    public static function tbkOrderDetails(
        int    $queryType,
        string $startTime,
        string $endTime,
        int    $pageSize = 20,
        int    $orderScene = 1,
        string $positionIndex = ''
    )
    {
        $req = new TbkOrderDetailsGetRequest;
        $req->setQueryType($queryType);//查询时间类型，1：按照订单淘客创建时间查询，2:按照订单淘客付款时间查询，3:按照订单淘客结算时间查询，4:按照订单更新时间；
        $req->setStartTime($startTime);//订单查询开始时间
        $req->setEndTime($endTime);//订单查询结束时间，订单开始时间至订单结束时间，中间时间段日常要求不超过3个小时，但如618、双11、年货节等大促期间预估时间段不可超过20分钟，超过会提示错误，调用时请务必注意时间段的选择，以保证亲能正常调用！
        $req->setOrderScene($orderScene);//场景订单场景类型，1:常规订单，2:渠道订单，3:会员运营订单，默认为1
        $req->setPageSize($pageSize);//页大小，默认20，1~100
        $req->setPositionIndex($positionIndex);//位点，除第一页之外，都需要传递；前端原样返回
        return self::handleDataResponse($req, 'taobao.tbk.order.details.get( 淘宝客-推广者-所有订单查询 )');
    }

    /**
     * @param string $activityMaterialId 官方活动会场ID，从淘宝客后台“我要推广-活动推广”中获取
     * @param int $adzoneId mm_xxx_xxx_xxx的第三位
     * @param string $subPid mm_xxx_xxx_xxx 仅三方分成场景使用
     * @param int $relationId 渠道关系id
     * @param string $unionId 自定义输入串，英文和数字组成，长度不能大于12个字符，区分不同的推广渠道
     * taobao.tbk.activity.info.get( 淘宝客-推广者-官方活动转链 )
     */
    public static function TbkActivityInfoGet(
        string $activityMaterialId,
        int    $adzoneId,
        string $subPid,
        int    $relationId,
        string $unionId = ''
    )
    {
        $req = new TbkActivityInfoGetRequest;
        $req->setAdzoneId($adzoneId);
        $req->setSubPid($subPid);
        $req->setRelationId($relationId);
        $req->setActivityMaterialId($activityMaterialId);
        $req->setUnionId($unionId);
        return self::handleDataResponse($req, 'taobao.tbk.activity.info.get( 淘宝客-推广者-官方活动转链 )');
    }

    /**
     * @param string $url
     * 原始url, 只支持uland.taobao.com，s.click.taobao.com， ai.taobao.com，temai.taobao.com的域名转换，否则判错
     * taobao.tbk.spread.get( 淘宝客-公用-长链转短链 )
     */
    public static function TbkSpreadGet(
        string $url
    )
    {
        $req = new TbkSpreadGetRequest;
        $requests = new TbkSpreadRequest;
        $requests->url = $url;
        $req->setRequests(json_encode($requests));
        $resp = self::topClient()->execute($req);
        $data = self::_getArrayData($resp);
        $msgKey = 'taobao.tbk.spread.get( 淘宝客-公用-长链转短链 )';
        if (isset($data['results']['tbk_spread'])) {
            return $data['results']['tbk_spread'] ?? [];
        } else {
            Log::error($msgKey, $resp);

            return [];
        }
    }

    public static function getItemIdByUrl($url)
    {
        $itemId = 0;
        if (filter_var($url, FILTER_VALIDATE_URL)) {
            $url = RealUrl::getRealUrl($url);
            $urlType = RealUrl::getUrlType($url);
            if ($urlType) {
                $itemId = RealUrl::getItemId($url, $urlType);
            }
        }
        return $itemId;
    }

    /**
     * @param $itemId 商品数字id
     * @param $newItemId 淘宝联盟加密商品id
     * @return string[]
     */
    public static function getTbkUrl($itemId, $newItemId = '')
    {
        $cacheTbkUrl = TbkUrl::getItem($itemId);
        $tbkUrl = $cacheTbkUrl['url'] ?? '';
        if (!$cacheTbkUrl) {//缓存
            if ($newItemId) {
                $res = TbkUnion::tbkCouponConvert($newItemId, TbkUnion::ADZONE_ID, '', TbkUnion::BIZ_SCENE_ID3);
            } else {
                $res = TbkUnion::tbkCouponConvert($itemId);
            }
            $tbkUrl = $res['item_url'] ?? '';
            $expire = $tbkUrl ? TbkUrl::_CACHE_EXPIRE_TIME : 86400;
            TbkUrl::setUrl($itemId, $tbkUrl, $expire);
        }
        return $tbkUrl;
    }

    /**
     * @param $itemId
     * @param int $bizSceneId 场景ID（见常量备注）
     * @return false|mixed
     */
    public static function getItemInfo($itemId, int $bizSceneId = self::BIZ_SCENE_ID1)
    {
        $result = self::tbkItemInfo($itemId, self::PLATFROM_MOBILE, $bizSceneId);

        return $result['n_tbk_item'][0] ?? false;
    }


    /**
     * @param $itemIds
     * @param int $bizSceneId 场景ID（见常量备注）
     * @return false|mixed
     */
    public static function getItemsInfo($itemIds, int $bizSceneId = self::BIZ_SCENE_ID1)
    {
        $result = self::tbkItemInfo($itemIds, self::PLATFROM_MOBILE, $bizSceneId);

        return $result['n_tbk_item'] ?? false;
    }

    /**
     * 淘口令解析
     * @param $passwordContent 淘口令
     * @param $adzoneId
     * @return void
     */
    public static function tpwdConvert($passwordContent, $adzoneId = self::ADZONE_ID)
    {
        $req = new \TbkTpwdConvertRequest();
        $req->setAdzoneId($adzoneId);
        $req->setPasswordContent($passwordContent);
        $resp = self::topClient()->execute($req);
        $data = self::_getArrayData($resp);
        return $data['data'] ?? [];
    }

    /**
     * 淘宝联盟数字ID批量转加密字符串ID API（联盟临时接口到2022-9-16）
     * @param array $itemIds
     * @return array
     */
    public static function tbkItemIdtransForm(array $itemIds)
    {
        if (empty($itemIds)) {
            return [];
        }
        $itemIdsStr = implode(',', $itemIds);
        $req = new \TbkItemidTransformRequest();
        $req->setItemIds($itemIdsStr);
        $resp = self::topClient()->execute($req);
        $transFormData = $resp['results']['item_id_transform_d_t_o'] ?? [];
        $transFormData = $transFormData ? array_column($transFormData, null, 'original_item_id') : [];
        $result = [];
        foreach ($itemIds as $itemId) {
            if (isset($transFormData[$itemId]['item_id'])) {
                $result[$itemId] = $transFormData[$itemId]['item_id'];
            }
        }
        return $result;
    }

    public static function getAppKey()
    {
        $config = self::_getAppConfig();
        $appKey = $config['default']['appkey'];
        return $appKey;
    }

    public static function createInviteUrl($uid, $scene = self::OAUTH_SCENE_DESIGNER_COMMERCE_RID)
    {
        $clinetId = self::getAppKey();
        $hashUid = IdParse::hashUid($uid);
        $expireTime = time() + self::OAUTH_SCENE_DESIGNER_COMMERCE_EXPIRE_TIME;
        $redirectUrl = self::$callBackUrl . '?uid=' . $hashUid . '&scene=' . $scene . '&stamp=' . IdParse::hashUid($expireTime);
        $redirectUrl = urlencode($redirectUrl);
        $state = self::INVITER_CODE_COMMON;//渠道备案邀请码，默认使用通用备案的邀请码
        $inviteUrl = sprintf(self::$oAuthUrl, $clinetId, $redirectUrl, $state);
        return $inviteUrl;
    }

    public static function createAccessToken($code)
    {
        $tokenResult = [];
        if ($code) {
            $req = new TopAuthTokenCreateRequest;
            $req->setCode($code);
            //$req->setUuid("abc");
            $resp = self::topClient()->execute($req);
            $data = self::_getArrayData($resp);
            if (isset($data['token_result'])) {
                Log::info('taobao.top.auth.token.create( 获取Access Token )', [$code]);
                $tokenResult = $data['token_result'];
                $tokenResult = json_decode($tokenResult, true);
            } else {
                Log::error('taobao.top.auth.token.create( 获取Access Token )', $resp);
                return $resp;
            }
        }
        return $tokenResult;
    }

    /**
     * 创建渠道关系Id
     * @param $sessionKey accesstoken
     * @param $note 媒体侧渠道备注
     * @param string $inviterCode 邀请码
     * @return \$1|false|mixed|\ResultSet|\SimpleXMLElement|void
     */
    public static function saveTbkScPublisherInfo($sessionKey, $note, $inviterCode = self::INVITER_CODE_COMMON)
    {
        $req = new TbkScPublisherInfoSaveRequest;
        //$req->setRelationFrom('');//渠道备案 - 来源，取链接的来源
        //$req->setOfflineScene('');//渠道备案 - 线下场景信息，1 - 门店，2- 学校，3 - 工厂，4 - 其他
        //$req->setOnlineScene('');//渠道备案 - 线上场景信息，1 - 微信群，2- QQ群，3 - 其他
        $req->setInviterCode($inviterCode);//淘宝客邀请渠道或会员的邀请码
        $req->setInfoType(1);//类型，必选 默认为1:
        $req->setNote($note);//媒体侧渠道备注
        //$req->setRegisterInfo('');//线下备案注册信息,字段包含: 电话号码(phoneNumber，必填),省(province,必填),市(city,必填),区县街道(location,必填),详细地址(detailAddress,必填),经营类型(career,线下个人必填),店铺类型(shopType,线下店铺必填),店铺名称(shopName,线下店铺必填),店铺证书类型(shopCertifyType,线下店铺选填),店铺证书编号(certifyNumber,线下店铺选填)
        $resp = self::topClient()->execute($req, $sessionKey);
        $data = self::_getArrayData($resp);
        if (isset($data['data'])) {
            Log::info('taobao.tbk.sc.publisher.info.save( 淘宝客-公用-私域用户备案 )', [$sessionKey, $note, $inviterCode]);
            $data = $data['data'];
            return $data;
        } else {
            Log::error('taobao.tbk.sc.publisher.info.save( 淘宝客-公用-私域用户备案 )', $resp);
            return $data;
        }
    }
}
